/*
 * app_sniff.c
 *
 *  Created on: 26 Aug 2021
 *      Author: NingTao.Huang
 */
#include "driver_Mobvoi_includes.h"
#include "app_Mobvoi_includes.h"
#include "Mobvoi_external.h"
#include "bt_init.h"
#include "tra_hcit.h"

#if CONFIG_CRTL_POWER_IN_BT_SNIFF_MODE

static BT_SNIFF_T g_sniff_st[NEED_SNIFF_DEVICE_COUNT];
void app_bt_write_sniff_link_policy(uint16_t link_handle, uint8_t set_link_policy)
{
    uint8_t idx;
    app_handle_t app_h = app_get_sys_handler();
    hci_write_link_policy_settings_cp lp_cp;
    hci_exit_sniff_mode_cp exit_cp;
#if (CONFIG_AS_SLAVE_ROLE == 1)
    btaddr_t *rmt_addr;
#endif
    if (!app_env_check_sniff_mode_Enable())
        return;
    if (app_h->unit == NULL)
        return;

    lp_cp.settings = app_h->unit->hci_link_policy;
    idx = bt_sniff_get_index_from_handle(link_handle);
    if (idx >= NEED_SNIFF_DEVICE_COUNT)
    {
        return;
    }
    bt_sniff_set_policy(idx, set_link_policy);
#if (CONFIG_AS_SLAVE_ROLE == 1)
    rmt_addr = bt_sniff_get_addrptr_from_idx(idx);
#endif
    if (set_link_policy)
    {
        LOG_I(SNIFF, "sniff enable:%d,%04x\r\n", idx, link_handle);
        lp_cp.con_handle = link_handle;
        lp_cp.settings |= HCI_LINK_POLICY_ENABLE_SNIFF_MODE;
        hci_send_cmd(app_h->unit, HCI_CMD_WRITE_LINK_POLICY_SETTINGS, (void *)&lp_cp, sizeof(lp_cp));
#if (CONFIG_AS_SLAVE_ROLE == 1)
        Judge_role(rmt_addr, FALSE);
#endif
    }
    else
    {
        if (!bt_sniff_is_active(idx))
        {
            LOG_I(SNIFF, "exit sniff:%d,%04x\r\n", idx, link_handle);
            exit_cp.con_handle = link_handle;
            hci_send_cmd(app_h->unit, HCI_CMD_EXIT_SNIFF_MODE, (void *)&exit_cp, sizeof(hci_exit_sniff_mode_cp));
            /* bt_sniff_set_active(idx,1);*/
        }
        /* else */
        {
            LOG_I(SNIFF, "sniff disable:%d,%04x\r\n", idx, link_handle);
            lp_cp.con_handle = link_handle;
            lp_cp.settings &= ~HCI_LINK_POLICY_ENABLE_SNIFF_MODE;
            hci_send_cmd(app_h->unit, HCI_CMD_WRITE_LINK_POLICY_SETTINGS, (void *)&lp_cp, sizeof(lp_cp));
#if (CONFIG_AS_SLAVE_ROLE == 1)
            Judge_role(rmt_addr, FALSE);
#endif
        }
    }
}
void app_bt_enter_sniff_mode(uint16_t link_handle, uint8_t enable)
{
    uint8_t idx;
    app_handle_t app_h = app_get_sys_handler();
    hci_sniff_mode_cp sniff_cp;
    hci_exit_sniff_mode_cp exit_cp;
    if (app_h->unit == NULL)
        return;
    idx = bt_sniff_get_index_from_handle(link_handle);
    if (idx >= NEED_SNIFF_DEVICE_COUNT)
    {
        return;
    }
    if (enable)
    {
        if (a2dp_has_music() || hfp_has_sco())
        {
            return;
        }
        else
        {
            sniff_cp.con_handle = link_handle;
#ifdef LE_SLEEP_ENABLE
            sniff_cp.max_interval = 0x320; /* 0x320=500ms */
            sniff_cp.min_interval = 0x280; /* 0x200=320ms;0x280=400ms;0x2A0=420ms;0x2D0=450ms */
#else
            sniff_cp.max_interval = 0x280; //0x500;   /* 0x0006 ~ 0x0540 */
            sniff_cp.min_interval = 0x200; //0x400;   /* 0x0006 ~ 0x0540 */
#endif
            sniff_cp.attempt = 4;
            sniff_cp.timeout = 4;
            LOG_I(SNIFF, "enter sniff:%d,%04x,slots:%d\r\n", idx, link_handle, sniff_cp.min_interval);
            hci_send_cmd(app_h->unit, HCI_CMD_SNIFF_MODE, (void *)&sniff_cp, sizeof(hci_sniff_mode_cp));
            /* bt_sniff_set_active(idx,0); */
        }
    }
    else
    {
        LOG_I(SNIFF, "exit sniff:%d,%04x\r\n", idx, link_handle);
        exit_cp.con_handle = link_handle;
        hci_send_cmd(app_h->unit, HCI_CMD_EXIT_SNIFF_MODE, (void *)&exit_cp, sizeof(hci_exit_sniff_mode_cp));
        /* bt_sniff_set_active(idx,1); */
    }
}

void bt_sniff_alloc_st(uint8_t idx, uint16_t handle, btaddr_t *rbtaddr)
{
    idx &= 0x01;
    g_sniff_st[idx].is_active = 1;
    g_sniff_st[idx].is_used = 1;
    g_sniff_st[idx].is_policy = 0;
    g_sniff_st[idx].link_handle = handle;

    memcpy((uint8_t *)&g_sniff_st[idx].remote_btaddr,
           (uint8_t *)rbtaddr,
           sizeof(btaddr_t));
}

void bt_sniff_free_st(uint8_t idx)
{
    idx &= 0x01;
    g_sniff_st[idx].is_active = 0;
    g_sniff_st[idx].is_used = 0;
    g_sniff_st[idx].link_handle = 0;
    g_sniff_st[idx].is_policy = 0;
}
uint8_t bt_sniff_find_st_available(void)
{
    uint8_t idx = 0;
    for (; idx < NEED_SNIFF_DEVICE_COUNT; idx++)
    {
        if (g_sniff_st[idx].is_used == 0)
        {
            return idx;
        }
    }
    return 0;
}
uint16_t bt_sniff_get_handle_from_raddr(btaddr_t *rbtaddr)
{
    uint8_t idx = 0;
    for (; idx < NEED_SNIFF_DEVICE_COUNT; idx++)
    {
        if (btaddr_same(rbtaddr, &g_sniff_st[idx].remote_btaddr))
        {
            return g_sniff_st[idx].link_handle;
        }
    }
    return 0;
}
uint8_t bt_sniff_get_index_from_raddr(btaddr_t *rbtaddr)
{
    uint8_t idx = 0;
    for (; idx < NEED_SNIFF_DEVICE_COUNT; idx++)
    {
        if (btaddr_same(rbtaddr, &g_sniff_st[idx].remote_btaddr))
        {
            return idx;
        }
    }
    return 0;
}
uint8_t bt_sniff_get_index_from_handle(uint16_t handle)
{
    uint8_t idx = 0;
    for (; idx < NEED_SNIFF_DEVICE_COUNT; idx++)
    {
        if (g_sniff_st[idx].link_handle == handle)
        {
            return idx;
        }
    }
    return 0;
}
uint16_t bt_sniff_get_handle_from_idx(uint8_t idx)
{
    return g_sniff_st[idx].link_handle;
}

btaddr_t bt_sniff_get_rtaddr_from_idx(uint8_t idx)
{
    return g_sniff_st[idx].remote_btaddr;
}
btaddr_t *bt_sniff_get_addrptr_from_idx(uint8_t idx)
{
    return (btaddr_t *)&g_sniff_st[idx].remote_btaddr;
}
uint8_t bt_sniff_is_used(uint8_t idx)
{
    return (g_sniff_st[idx].is_used);
}
uint8_t bt_sniff_is_active(uint8_t idx)
{
    return (g_sniff_st[idx].is_active);
}
uint8_t bt_sniff_is_policy(uint8_t idx)
{
    return (g_sniff_st[idx].is_policy);
}
void bt_sniff_set_policy(uint8_t idx, uint8_t enable)
{
    g_sniff_st[idx].is_policy = enable;
}
void bt_sniff_set_active(uint8_t idx, uint8_t enable)
{
    g_sniff_st[idx].is_active = enable & 0x01;
}
uint8_t bt_sniff_is_all_active(void)
{
    uint8_t idx = 0;

    for (idx = 0; idx < NEED_SNIFF_DEVICE_COUNT; idx++)
    {
        if (!g_sniff_st[idx].is_active)
        {
            return FALSE;
        }
    }

    return TRUE;
}
void bt_sniff_all_exit_mode(void)
{
    uint8 idx = 0;

    for (idx = 0; idx < NEED_SNIFF_DEVICE_COUNT; idx++)
    {
        if (bt_sniff_is_used(idx))
        {
            if (bt_sniff_is_policy(idx))
            {
                app_bt_write_sniff_link_policy(bt_sniff_get_handle_from_idx(idx), 0);
            }
        }
    }
}
#else
uint8_t bt_sniff_get_index_from_handle(uint16_t handle)
{
    return 0;
}
uint16_t bt_sniff_get_handle_from_idx(uint8_t idx)
{
    return 0;
}
uint8_t bt_sniff_is_used(uint8_t idx)
{
    return 0;
}
uint8_t bt_sniff_is_active(uint8_t idx)
{
    return 0;
}
void bt_sniff_set_active(uint8_t idx, uint8_t enable)
{
}
void app_bt_write_sniff_link_policy(uint16_t link_handle, uint8_t set_link_policy)
{
}
#endif
